<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0">
 <channel>
  <title>Gnaily's Blog: Gnaily's Blog</title>
  <description>Gnaily's Blog: Gnaily's Blog</description>
  <link>http://yangliang.site/index.html</link>
  <lastBuildDate>Fri, 31 Aug 2018 16:00:00 UT</lastBuildDate>
  <pubDate>Fri, 31 Aug 2018 16:00:00 UT</pubDate>
  <ttl>1800</ttl>
  <item>
   <title>Spring Framework</title>
   <link>http://yangliang.site/2018\09\spring-framework.html?utm_source=all&amp;utm_medium=RSS</link>
   <guid isPermaLink="false">urn:http-yangliang-site:-2018-09-spring-framework-html</guid>
   <pubDate>Fri, 31 Aug 2018 16:00:00 UT</pubDate>
   <author>Gnaily</author>
   <description>
&lt;p&gt;[TOC]&lt;/p&gt;

&lt;h1 id="spring"&gt;Spring&lt;/h1&gt;

&lt;blockquote&gt;
 &lt;p&gt;Spring 参考文档&lt;/p&gt;
 &lt;p&gt;Spring core&lt;/p&gt;
 &lt;p&gt;https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/core.html&lt;/p&gt;
 &lt;p&gt;Spring mvc&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Sping将程序看成由各个组件相互组装而成，&lt;code&gt;抽象出组件和组装组件的容器&lt;/code&gt;。应用程序中通过组件的配置信息（xml、java注解、java代码）告诉容器如何初始化、配置和组件组件，Spring扫描配置信息，然后按照配置信息组装出程序。这就是Spring的核心原理。&lt;/p&gt;

&lt;div class="figure"&gt;&lt;img src="C:UsersGnailyAppDataLocalTemp1523797001169.png" alt="1523797001169" /&gt;
 &lt;p class="caption"&gt;1523797001169&lt;/p&gt;&lt;/div&gt;

&lt;h3 id="应用程序组件的表示spring-bean"&gt;应用程序组件的表示——Spring Bean&lt;/h3&gt;

&lt;p&gt;Spring使用Bean来表示应用程序组件，在Spring中每一个应用程序组件都是一个Bean实体。Spring的Bean可以是任何形式的POJO。&lt;/p&gt;

&lt;p&gt;Bean的作用域：&lt;/p&gt;

&lt;p&gt;| Scope | Description | | &amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash; | &amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash; | | &lt;a href="https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/core.html#beans-factory-scopes-singleton"&gt;singleton&lt;/a&gt; | (Default) Scopes a single bean definition to a single object instance per Spring IoC container. | | &lt;a href="https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/core.html#beans-factory-scopes-prototype"&gt;prototype&lt;/a&gt; | Scopes a single bean definition to any number of object instances. | | &lt;a href="https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/core.html#beans-factory-scopes-request"&gt;request&lt;/a&gt; | Scopes a single bean definition to the lifecycle of a single HTTP request; that is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring &lt;code&gt;ApplicationContext&lt;/code&gt;. | | &lt;a href="https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/core.html#beans-factory-scopes-session"&gt;session&lt;/a&gt; | Scopes a single bean definition to the lifecycle of an HTTP &lt;code&gt;Session&lt;/code&gt;. Only valid in the context of a web-aware Spring &lt;code&gt;ApplicationContext&lt;/code&gt;. | | &lt;a href="https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/core.html#beans-factory-scopes-application"&gt;application&lt;/a&gt; | Scopes a single bean definition to the lifecycle of a &lt;code&gt;ServletContext&lt;/code&gt;. Only valid in the context of a web-aware Spring &lt;code&gt;ApplicationContext&lt;/code&gt;. | | &lt;a href="https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/web.html#websocket-stomp-websocket-scope"&gt;websocket&lt;/a&gt; | Scopes a single bean definition to the lifecycle of a &lt;code&gt;WebSocket&lt;/code&gt;. Only valid in the context of a web-aware Spring &lt;code&gt;ApplicationContext&lt;/code&gt;. |&lt;/p&gt;

&lt;p&gt;Bean的配置：&lt;/p&gt;

&lt;p&gt;xml配置Bean：在xml文件中配置一个Bean时，用一个唯一的id来标识这个Bean,用class指定该Bean的类的全限定名（包名.类名）。&lt;/p&gt;

&lt;div class="brush: xml"&gt;
 &lt;pre&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd"&amp;gt;
 
    &amp;lt;bean id="..." class="..."&amp;gt;
        &amp;lt;!-- collaborators and configuration for this bean go here --&amp;gt;
    &amp;lt;/bean&amp;gt;
 
    &amp;lt;bean id="..." class="..."&amp;gt;
        &amp;lt;!-- collaborators and configuration for this bean go here --&amp;gt;
 
    &amp;lt;!-- more bean definitions go here --&amp;gt;
 
&amp;lt;/beans&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;注解配置Bean：在POJO的类上添加@Bean注解。&lt;/p&gt;

&lt;h3 id="应用程序组件的组装spring-依赖注入与控制反转"&gt;应用程序组件的组装——Spring 依赖注入与控制反转&lt;/h3&gt;

&lt;h4 id="依赖注入dependency-injection"&gt;依赖注入（Dependency Injection）&lt;/h4&gt;

&lt;p&gt;一个对象不在自己的内部构造出它所依赖的对象，它所依赖的对象由第三方构造然后通过该对象的&lt;code&gt;构造方法&lt;/code&gt;或者&lt;code&gt;setter方法&lt;/code&gt;注入进来。&lt;/p&gt;

&lt;h4 id="控制反转容器ioc-container"&gt;控制反转容器（IoC Container）&lt;/h4&gt;

&lt;p&gt;Spring通过一个容器来根据一个对象的配置信息（xml、java注解、java代码）组装所依赖的Bean实例，并将组装出的Bean实例注入到该对象中。Spring中的这个容器控制着所有应用组件（Bean对象）的整个生命周期，从如何产生到如何销毁，而原本这些对象的生命周期都是由其依赖的对象直接控制的，这个容器被叫做控制反转容器，因为它反转了对象的控制权。Spring容器是Spring的核心。&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  &lt;p&gt;&lt;code&gt;org.springframework.beans&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
 &lt;li&gt;
  &lt;p&gt;&lt;code&gt;org.springframework.context&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;h3 id="应用程序资源spring-resource"&gt;应用程序资源——Spring Resource&lt;/h3&gt;

&lt;p&gt;Spring内部自定义的资源：&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  &lt;p&gt;UrlResource：wraps a &lt;code&gt;java.net.URL&lt;/code&gt;, and may be used to access any object that is normally accessible via a URL, such as files, an HTTP target, an FTP target, etc.&lt;/p&gt;&lt;/li&gt;
 &lt;li&gt;ClassPathResource：represents a resource which should be obtained from the classpath.This uses either the thread context class loader, a given class loader, or a given class for loading resources.&lt;/li&gt;
 &lt;li&gt;FileSystemResource：a &lt;code&gt;Resource&lt;/code&gt; implementation for &lt;code&gt;java.io.File&lt;/code&gt; handles. It obviously supports resolution as a &lt;code&gt;File&lt;/code&gt;, and as a &lt;code&gt;URL&lt;/code&gt;.&lt;/li&gt;
 &lt;li&gt;ServletContextResource：a &lt;code&gt;Resource&lt;/code&gt; implementation for &lt;code&gt;ServletContext&lt;/code&gt; resources, interpreting relative paths within the relevant web application’s root directory&lt;/li&gt;
 &lt;li&gt;InputStreamResource：implementation for a given &lt;code&gt;InputStream&lt;/code&gt;. This should only be used if no specific &lt;code&gt;Resource&lt;/code&gt; implementation is applicable.&lt;/li&gt;
 &lt;li&gt;ByteArrayResource：a &lt;code&gt;Resource&lt;/code&gt; implementation for a given byte array&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;资源加载器（ResourceLoader）：&lt;/p&gt;

&lt;p&gt;资源加载器用来实现在应用程序中加载资源。 Spring中ResourceLoader接口定义如下所示。 Spring中所用的应用程序上下文都实现了该接口。所以如果在应用程序中想要获取资源，可以通过应用程序上下文来获取。例如applicationContext.getResource(&amp;ldquo;http://myhost.com/resource/path/myTemplate.txt&amp;rdquo;)；&lt;/p&gt;

&lt;div class="brush: java"&gt;
 &lt;pre&gt;&lt;code&gt;public interface ResourceLoader {
 
    Resource getResource(String location);
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="应用程序数据处理验证数据绑定和类型转换"&gt;应用程序数据处理——验证、数据绑定和类型转换&lt;/h3&gt;

&lt;h4 id="validation"&gt;Validation&lt;/h4&gt;

&lt;h4 id="data-binding"&gt;Data Binding&lt;/h4&gt;

&lt;h4 id="type-convertion"&gt;Type Convertion&lt;/h4&gt;

&lt;p&gt;Spring 提供了一个通用的类型转换系统,可以用来进行类型之间的转换。其接口定义如下：&lt;/p&gt;

&lt;div class="brush: java"&gt;
 &lt;pre&gt;&lt;code&gt;package org.springframework.core.convert.converter;
 
public interface Converter&amp;lt;S, T&amp;gt; {
 
    T convert(S source);
 
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="切面编程spring-aop"&gt;切面编程——Spring AOP&lt;/h3&gt;

&lt;h4 id="aop原理"&gt;AOP原理&lt;/h4&gt;

&lt;h4 id="spring-aop中的概念"&gt;Spring AOP中的概念&lt;/h4&gt;

&lt;p&gt;AOP框架是Spring的一个关键组件。AOP的应用如权限管理、日志记录、事务的。Spring中AOP的概念：&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  &lt;p&gt;&lt;em&gt;Aspect&lt;/em&gt; ：切面，对跨越多个类的关注点的模块化抽象。&lt;/p&gt;&lt;/li&gt;
 &lt;li&gt;&lt;em&gt;Join point&lt;/em&gt; ：接入点，表示程序执行期间的一个位置，比如程序中某个方法调用前的地方，方法调用异常的地方或者方法调用结束的地方，这些位置可以接入一些切面的行为。&lt;/li&gt;
 &lt;li&gt;&lt;em&gt;Advice&lt;/em&gt; ：表示切面在特殊接入点（join point）的行为。&lt;/li&gt;
 &lt;li&gt;&lt;em&gt;Pointcut&lt;/em&gt; ：切点，对接入点（join point）的匹配预测。Advice 被关联到一个pointcut表达式，它会在匹配 pointcut表达式的任何接入点处执行行。&lt;/li&gt;
 &lt;li&gt;&lt;em&gt;Introduction&lt;/em&gt; ：在一个类型上声明附加的方法和字段&lt;/li&gt;
 &lt;li&gt;&lt;em&gt;Target object&lt;/em&gt; : 目标对象。&lt;/li&gt;
 &lt;li&gt;&lt;em&gt;AOP proxy&lt;/em&gt; ：AOP 框架为实现切面契约而创建的对象，它是Target object的代理对象。&lt;/li&gt;
 &lt;li&gt;&lt;em&gt;Weaving&lt;/em&gt; ：&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;JDk动态代理实现AOP：&lt;/p&gt;

&lt;div class="brush: java"&gt;
 &lt;pre&gt;&lt;code&gt;public abstract class Aspect implements InvocationHandler {
 
    private Object target;
 
    public Aspect(Object target) {
        this.target = target;
    }
 
    /**
     * Returns target object.
     */
    public final Object getTarget() {
        return this.target;
    }
 
    /**
     * Runs before targets method. Returns {@code true} if target method
     * should run.
     */
    public abstract boolean before(Object target, Method method, Object[] args);
 
    /**
     * Runs after targets method. Returns {@code true} if aspect method should
     * return value, otherwise {@code null}.
     */
    public abstract boolean after(Object target, Method method, Object[] args);
 
    /**
     * Invoked after exception.
     */
    public abstract boolean afterException(Object target, Method method, Object[] args, Throwable throwable);
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
 
        if (before(target, method, args)) {
            try {
                result = method.invoke(target, args);
            }
            catch (InvocationTargetException e) {
                afterException(args, method, args, e.getTargetException());
            }
            catch (Exception ex) {
                throw ex;
            }
        }
        if (after(target, method, args)) {
            return result;
        }
        return null;
    }
 
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="brush: java"&gt;
 &lt;pre&gt;&lt;code&gt;public class AopProxy {
 
    /**
     * Creates a proxy of given target and the aspect.
     */
    @SuppressWarnings("unchecked")
    public static &amp;lt;T&amp;gt; T proxyOf(T target, Class&amp;lt;? extends Aspect&amp;gt; aspectClass) {
        final Aspect aspect;
 
        try {
            aspect = ClassUtil.newInstance(aspectClass, target);
        }
        catch (Exception e) {
            throw new IllegalArgumentException("Can't create new instance of aspect class", e);
        }
 
        return (T) newProxyInstance(target.getClass().getClassLoader(), aspect, target.getClass().getInterfaces());
    }
 
    /**
     * Creates a proxy from given {@link Aspect}.
     */
    @SuppressWarnings("unchecked")
    public static &amp;lt;T&amp;gt; T proxyOf(Aspect aspect) {
        final Object target = aspect.getTarget();
        return (T) newProxyInstance(target.getClass().getClassLoader(), aspect, target.getClass().getInterfaces());
    }
 
    /**
     * Simple wrapper for javas {@code newProxyInstance}.
     */
    @SuppressWarnings("unchecked")
    public static &amp;lt;T&amp;gt; T newProxyInstance(ClassLoader classloader, InvocationHandler invocationHandler, Class&amp;lt;?&amp;gt;... interfaces) {
        if (interfaces.length == 0) {
            throw new IllegalArgumentException("No interfaces of target class found.");
        }
        return (T) Proxy.newProxyInstance(classloader, interfaces, invocationHandler);
    }
 
}
 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="spring事务"&gt;Spring事务&lt;/h3&gt;

&lt;h3 id="springmvc"&gt;SpringMVC&lt;/h3&gt;</description></item>
  <item>
   <title>简明SQL</title>
   <link>http://yangliang.site/2018\04\%E7%AE%80%E6%98%8Esql.html?utm_source=all&amp;utm_medium=RSS</link>
   <guid isPermaLink="false">urn:http-yangliang-site:-2018-04-E7-AE-80-E6-98-8Esql-html</guid>
   <pubDate>Thu, 05 Apr 2018 16:00:00 UT</pubDate>
   <author>Gnaily</author>
   <description>
&lt;p&gt;[TOC]&lt;/p&gt;

&lt;h3 id="表结构操作"&gt;表结构操作&lt;/h3&gt;

&lt;p&gt;查看表结构&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;desc  tablename ; -- 查看表tablename的结构信息&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;创建表结构&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;CREATE TABLE tablename(
  -- db_data_type是数据库的数据类型，比如int(5)，varchar(64)
  column_name_1   db_data_type
  column_name_2   db_data_type
  ...
  column_name_n   db_data_type 
) ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;增加表的字段&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;alter tablename
-- db_data_type是数据库的数据类型，比如int()，varchar(64)
add   column_name_1   db_data_type
add   column_name_2   db_data_type
...
add   column_name_n   db_data_type ; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;删除表的字段&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;alter tablename
drop  column column_name_1  
drop  column column_name_2
...
drop  column column_name_n ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;删除表&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;drop tablename ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;创建索引：&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- 在table_name表的column_name列上创建一个简单的索引。允许使用重复的索引值。
create index index_name
on tablename (column_name) ;
 
-- 在table_name表的column_name列上创建一个唯一的索引。唯一的索引意味着任意两个行不能拥有相同的索引值。
create uinqe index index_name
on tablename (column_name) ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="检索数据select"&gt;检索数据select&lt;/h3&gt;

&lt;p&gt;数据检索SQL一般由select子句，from子句，join子句、where子句、group by子句、having子句 、order by子句组成。from子句后的其他子句不是必须要有的，根据实际需要进行使用。各个子句出现的相对顺序不能颠倒。Select检索数据的&lt;code&gt;逻辑&lt;/code&gt;处理流程为：&lt;/p&gt;

&lt;p&gt;join连接表&amp;mdash;&amp;gt;where 对行过滤&amp;mdash;&amp;gt;group by分组&amp;mdash;&amp;gt;having对组过滤&amp;mdash;&amp;gt;聚集函数处理&amp;mdash;&amp;gt;order by排序&amp;mdash;&amp;gt;输出结果。&lt;/p&gt;

&lt;p&gt;当有子查询时先处理内层子查询，再处理外层查询。&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;select
   列名 -- 多个列名用逗号隔开，非聚集列（没有被聚集函数作用的列）必须是分组列名的子集
from
   表名
left|right|inner  join   表名   on   关联条件
where  
   过滤行条件
group by  
   分组列名  -- 多个列名用逗号隔开
having
   过滤分组条件  -- 过滤分组条件中的非聚集列（没有被聚集函数作用的列）必须是分组列名的子集
order by
   排序字段&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;简单检索SQL&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- 检索tablename表的所有列的结果
select *  from tablename;
-- 检索tablename表的指定列的结果
select column_name_1,column_name_2,... column_name_n from tablename; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;过滤行使用where&lt;/p&gt;

&lt;p&gt;where关系运算符：&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;大于( &amp;gt;）:只检索出满足指定字段大于指定值的数据，其余被过滤掉。&lt;/li&gt;
 &lt;li&gt;小于（&amp;lt;）：只检索出满足指定字段小于指定值的数据，其余被过滤掉&lt;/li&gt;
 &lt;li&gt;等于（=）：只检索出满足指定字段等于指定值的数据，其余被过滤掉&lt;/li&gt;
 &lt;li&gt;大于或等于（&amp;gt;=）:只检索出满足指定字段大于或等于指定值的数据，其余被过滤掉&lt;/li&gt;
 &lt;li&gt;小于或等于（&amp;lt;=）:只检索出满足指定字段小于或等于指定值的数据，其余被过滤掉&lt;/li&gt;
 &lt;li&gt;不等于（&amp;lt;&amp;gt;或！=）：只检索出满足指定字段不等于指定值的数据，其余被过滤掉&lt;/li&gt;
 &lt;li&gt;in操作符：只检索出满足指定字段在指定数据集合里的数据，其余被过滤掉&lt;/li&gt;
 &lt;li&gt;like通配匹配符：只检索出满足指定字段能与like后跟的搜索模式匹配的数据，其余被过滤掉&lt;/li&gt;
 &lt;li&gt;百分号通配符（%）：匹配任意字符出现任意次数。可以用在搜索模式的开始、中间和结尾处。&lt;/li&gt;
 &lt;li&gt;下划线通配符（_）:只匹配单个字符&lt;/li&gt;
 &lt;li&gt;方括号通配符（[ ]）：方括号通配符里用于指定一个字符集， 只匹配出一个在该字符集里的字符。&lt;/li&gt;
 &lt;li&gt;and操作符：组合多个条件，检索出同时满足多个条件的数据&lt;/li&gt;
 &lt;li&gt;or操作符：组合多个条件，检索出满足条件之一的数据&lt;/li&gt;&lt;/ul&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- useage:
where
    column_name_1=value1
and column_name_2&amp;gt;value2
and column_name_3 in ('张三'，'李四')
    -- 匹配end结尾的字符串
and column_name_4 like '%end' &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;检索结果分组用group by&lt;/p&gt;

&lt;p&gt;group by关键字指示DBMS对指定列中数据都相同的分为一组，group by 后的列相当分组的维度。&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;group by 可以包含任意数目的列&lt;/li&gt;
 &lt;li&gt;group by 子句中列出的每个列都必须是检索列或有效表达式（不能是聚集函数）。如果select 中使用列表达式，group by 中也要是表达式而不能是表达式的别名。&lt;/li&gt;
 &lt;li&gt;除进行聚集计算的列外，select中的每个列必须是group by中给出的列。&lt;/li&gt;
 &lt;li&gt;分组列中如果有null值，则列的所有null值将分为一个组&lt;/li&gt;&lt;/ul&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- useage:
select
    -- select输出的列必须是group by中的列
    column_name_1,column_name_2 
from
    tablename
group by
    -- 检索数据中这几个分组列的各个列的值相同的分为一组
    column_name_1,column_name_2,column_name_3 ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;过滤检索结果中的分组用having&lt;/p&gt;

&lt;p&gt;where对行进行过滤，having则对组进行过滤。having支持所有where子句中的操作符号。由于where在对数据分组前进数据行过滤，having则在分组后进行组的过滤，所以where排除的行不会包含在分组中，having过滤条件的字段必须是group by 中的字段。where中不能包含聚集函数，而having中可以包含聚集函数。&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- useage:
select
    -- select输出的列必须是group by中的列
    column_name_1,column_name_2 
from
    tablename
group by
    -- 检索数据中这几个分组列的各个列的值相同的分为一组
    column_name_1,column_name_2,column_name_3
having
      column_name_1=value1
  and column_name_2&amp;gt;value2 ; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;排序检索结果用order by&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;select
    column_name_1,column_name_2,column_name_3,column_name_4 
from
    tablename
order by
    column_name_2 desc,column_name_3 asc ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;汇总检索结果使用聚集函数&lt;/p&gt;

&lt;p&gt;聚集函数：运行在列的分组上，返回单个值的函数。如果有进行分组，聚集函数在分组后进行聚集&lt;/p&gt;

&lt;p&gt;常用聚集函数：&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;AVG（column）：返回指定列的均值&lt;/li&gt;
 &lt;li&gt;COUNT（column）：返回指定列的值的数目&lt;/li&gt;
 &lt;li&gt;MAX（column）：返回指定列的最大值&lt;/li&gt;
 &lt;li&gt;MIN（column）：返回指定列的最大值&lt;/li&gt;
 &lt;li&gt;SUM（column）：返回指定列值之和&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;聚集函数参数：聚集函数作用的的列名前可以加上distinct或all参数。all为默认参数，聚集函数作用的的列名前不加参数时默认为all，会对指定列的所用行进行计算，如果聚集函数作用的的列名前加上distinct参数，只会对指定列的不同值进行计算。有些数据库并不支持distinct。&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- useage:
select
    -- select输出的非聚集列必须是group by中的列
    AVG(column_name_1) ,
    COUNT(column_name_2) ,
    MAX(column_name_3)
    SUM(column_name_5),
    column_name_6,
    column_name_7
from
    tablename
where
    	column_name_1=value1
	and column_name_2&amp;gt;value2
group by
    -- 检索数据中这几个分组列的各个列的值相同的分为一组
    column_name_6,
    column_name_7
    column_name_8
having
      MIN(column_name_4)=value ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;关联查询用join&amp;hellip;on&amp;hellip;&lt;/p&gt;

&lt;p&gt;关联查询中的笛卡尔积&lt;/p&gt;

&lt;p&gt;左连接left join right-table on&amp;hellip;:包含左表的所有记录甚至是右表中没有和它匹配的记录。&lt;/p&gt;

&lt;p&gt;右连接right join right-table on&amp;hellip;:包含右表的所有记录甚至是左表中没有和它匹配的记录。&lt;/p&gt;

&lt;p&gt;内连接inner join&amp;hellip;.on&amp;hellip; :又称之为等值连接。仅仅选出两张表中互相匹配的记录&lt;/p&gt;

&lt;p&gt;关联查询耗资源，不要连接不必要的表。&lt;/p&gt;

&lt;p&gt;关联查询与子查询可转换。&lt;/p&gt;

&lt;p&gt;自连接：&lt;/p&gt;

&lt;p&gt;全外部连接&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- useage
 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;组合查询使用union&lt;/p&gt;

&lt;p&gt;union 操作符用于合并两个或多个 select 语句的结果集，要求select 子句的列的数据类型相似。&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  &lt;p&gt;多个查询中从不同表返回类似结构数据&lt;/p&gt;&lt;/li&gt;
 &lt;li&gt;
  &lt;p&gt;对单个表执行多个查询，按单个表返回查询数据&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;union的结果不包含重复值，union all的结果包含重复值。&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- useage
 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;子查询：嵌套在其他查询中的完整查询语句，可以嵌套的地方有&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;把子查询用作返回列&lt;/li&gt;
 &lt;li&gt;把子查询用作where条件&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;子查询总是从内向外处理。做为子查询的select语句只能查询单个列。&lt;/p&gt;

&lt;h3 id="插入数据insert"&gt;插入数据insert&lt;/h3&gt;

&lt;p&gt;插入一行数据&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;insert into tablename (column_name_1,column_name_2, ... column_name_n) values(value1,value2, ... valuen );&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;插入从表中检索出来的数据（可以是多行）insert into..select&amp;hellip;&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;insert into  tablename (column_name_1,column_name_2, ... column_name_n)
-- 这里是一条检索数据的sql
select column_name_1,column_name_2, ... column_name_n from ....  ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;复制数据到一个表中 select &amp;hellip;into&amp;hellip;&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- useage:
select column_name_1,column_name_2, ... column_name_n into tablename
from tablename
[left join ...  on ... ]
[where ... ]
[group by ... ]
[having ... ]
[order by ... ]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="更新数据update"&gt;更新数据update&lt;/h3&gt;

&lt;p&gt;使用where条件限定需要更新的行，省略where将更新整个表。编写时需要注意where条件的正确性，避免误操作。&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- 更新满足where限定条件的行，省略where将更新表的所有行
update
  tablename 
set
  column_name_1=value1 ,
  column_name_2=value2,
  ...
  column_name_n=valuen
where ...;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="删除数据delete"&gt;删除数据delete&lt;/h3&gt;

&lt;p&gt;使用where条件限定需要删除的行，省略where将删除整个表的数据。编写时需要注意where条件的正确性，避免误操作。&lt;/p&gt;

&lt;div class="brush: sql"&gt;
 &lt;pre&gt;&lt;code&gt;-- 从tablename表删除满足where条件的行，省略where时将删除改表的所有数据
delete from tablename  where ... ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="sql优化思路"&gt;SQL优化思路&lt;/h3&gt;

&lt;ul&gt;
 &lt;li&gt;优化select子句&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt; 用需要查询列的名字代替通配符*。使用SELECT &lt;em&gt;时一方面数据库需要去查询表的元数据来将&lt;/em&gt; 解析为表的具体字段， 另一方面会查询出表所有列的数据，而有的列的数据我们并不需要。这两者都会造成执行效率的下降。&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  &lt;p&gt;优化join子句&lt;/p&gt;&lt;/li&gt;
 &lt;li&gt;
  &lt;p&gt;优化where子句&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt; 优化or条件：对于含有or的查询子句，如果要利用索引，则or之间的每个条件都必须要用到索引；如果没有索引则需要考虑增加索引。&lt;/p&gt;

&lt;p&gt; 优化or为union查询。&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  &lt;p&gt;优化子查询为关联查询：join之所以比子查询更有效率是因为其不需要建立临时表来完成这个需要多个查询步骤的工作。&lt;/p&gt;&lt;/li&gt;
 &lt;li&gt;
  &lt;p&gt;使用SQL hint ：在SQL中人为加入提示来达到优化操作的目的。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</description></item></channel></rss>